package com.zhuhuix.startup.security.rest;

import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @program: unimall
 * @description: 工具类,单例模式获取AccessToken
 * @author: lee
 * @create: 2021-01-01 16:35
 **/

@Slf4j
@Component
public class AccessTokenFactory {

    //从配置文件拿到APPID和APPSECRET 并封装为常量
    private static String APPID;
    private static String APPSECRET;
    private static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

    private volatile static AccessToken uniqueSingleton;

    private AccessTokenFactory() {
    }

    public static String getAPPID(){
        return APPID;
    }

    @Value("${wxMini.appId}")
    public void setAPPID(String appId) {
        AccessTokenFactory.APPID = appId;
    }

    @Value("${wxMini.secret}")
    public void setAPPSECRET(String secret) {
        AccessTokenFactory.APPSECRET = secret;
    }



    public static AccessToken getInstance() throws IOException, ClassNotFoundException {
        if (null == uniqueSingleton) {
            synchronized (AccessTokenFactory.class) {
                if (null == uniqueSingleton) {
                    uniqueSingleton = getAccessToken();
                }
            }
        }
        return uniqueSingleton;
    }
    /**
     * 编写Get请求的方法。没有参数传递的时候，可以使用Get请求
     * @param url 需要请求的URL
     * @return 将请求URL后返回的数据，转为JSON格式，并return
     */
    private static JSONObject doGetStr(String url) throws ClientProtocolException, IOException {
        DefaultHttpClient client = new DefaultHttpClient();//获取DefaultHttpClient请求
        HttpGet httpGet = new HttpGet(url);//HttpGet将使用Get方式发送请求URL
        JSONObject jsonObject = null;
        HttpResponse response = client.execute(httpGet);//使用HttpResponse接收client执行httpGet的结果
        HttpEntity entity = response.getEntity();//从response中获取结果，类型为HttpEntity
        if(entity != null){
            String result = EntityUtils.toString(entity,"UTF-8");//HttpEntity转为字符串类型
            jsonObject = JSONObject.fromObject(result);//字符串类型转为JSON类型
        }
        return jsonObject;
    }

    /**
     * 获取AccessToken
     * @return 返回拿到的access_token及有效期
     */
    public static AccessToken getAccessToken() throws ClientProtocolException, IOException, ClassNotFoundException {
        AccessToken token = readAccessToken();
        if (null != token && (token.getAccessTime() + token.getExpiresIn() * 800L) > System.currentTimeMillis())
            return token;

        token = new AccessToken();
        String url = ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);//将URL中的两个参数替换掉
        JSONObject jsonObject = doGetStr(url);//使用刚刚写的doGet方法接收结果
        if(jsonObject!=null){ //如果返回不为空，将返回结果封装进AccessToken实体类
            token.setToken(jsonObject.getString("access_token"));//取出access_token
            token.setExpiresIn(jsonObject.getInt("expires_in"));//取出access_token的有效期
            token.setAccessTime(System.currentTimeMillis());
        }
        writeAccessToken(token);
        return token;
    }
    private static void writeAccessToken(AccessToken accessToken) throws IOException {
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("accessToken.txt"));
        objectOutputStream.writeObject(accessToken);
        objectOutputStream.close();
    }
    private static AccessToken readAccessToken(){
        ObjectInputStream objectInputStream = null;
        try {
            objectInputStream = new ObjectInputStream(new FileInputStream("accessToken.txt"));
        } catch (IOException e) {
            log.debug("accessToken.txt (系统找不到指定的文件。)");
            return null;
        }
        Object object = null;
        try {
            object = objectInputStream.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        AccessToken accessToken = (AccessToken) object;
        return accessToken;
    }

    /**
     * 生成带参小程序二维码
     * @param sceneStr	参数
     */
    public static void getMiniQr(String sceneStr) throws IOException, ClassNotFoundException {
        String accessToken = getInstance().getToken();
        try
        {
            URL url = new URL("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+accessToken);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setRequestMethod("POST");// 提交模式
            // conn.setConnectTimeout(10000);//连接超时 单位毫秒
            // conn.setReadTimeout(2000);//读取超时 单位毫秒
            // 发送POST请求必须设置如下两行
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
            // 发送请求参数
            JSONObject paramJson = new JSONObject();
            paramJson.put("scene", sceneStr);
            paramJson.put("page", "pages/index/index");
            paramJson.put("width", 430);
            paramJson.put("auto_color", true);
            /**
             * line_color生效
             * paramJson.put("auto_color", false);
             * JSONObject lineColor = new JSONObject();
             * lineColor.put("r", 0);
             * lineColor.put("g", 0);
             * lineColor.put("b", 0);
             * paramJson.put("line_color", lineColor);
             * */

            printWriter.write(paramJson.toString());
            // flush输出流的缓冲
            printWriter.flush();
            //开始获取数据
            BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream());
            OutputStream os = new FileOutputStream(new File("C:/Users/Administrator/Desktop/1.png"));
            int len;
            byte[] arr = new byte[1024];
            while ((len = bis.read(arr)) != -1)
            {
                os.write(arr, 0, len);
                os.flush();
            }
            os.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
